总结
ps -ef
: 显示所有程序,结合sort -k
排序目前 CPU 或 内存占用情况top
: 更好用的监控系统资源占用情况,P
CPU 排序,M
内存排序sort [File...]
: 默认按第一列字符ASCII
排序。可以多个文件内容一块排序-r
: 降序排序-k x,x
: 按列排序,显性设定End
在同一列,符合我们的惯性思维。-t
: 指定分隔符-n
: 按数字大小排序
需要留意,如果
sort -k x
未指明End
,排序内容为起始点到行末,排序时并没有列的概念,分隔符只服务于找到两个点,找到两个点后取出两点间的文本,分隔符被过滤掉。详细可以看文中--分隔符与排序的关系
1. 前提提要、场景
ps aux
可以显示所有的程序进程(不推荐)
a
: 显示现行终端机下的所有程序,包括其他用户的程序u
: 以用户为主的格式来显示程序状况x
: 显示所有程序,不以终端机来区分
ps -ef
也可以显示所有的程序进程(推荐)
ps aux
会截断command
列,而-ef
不会,所以推荐使用ps -ef
替代ps aux
当系统卡顿的时候,我们需要查看系统的资源占用情况,并且排序占用内存、CPU 占用最高的程序靠前。这时候可以使用 sort
命令排序。
查询系统资源占用情况,更快捷的方式是使用
top
命令,在top
窗口中,P
CPU 排序,M
内存排序
2. sort 默认首字母排序
- 示例文件准备sh
$ cat <<EOF > sort.md A 4 C 2 B 3 D 1 EOF $ cat <<EOF > sort1.md A 14 C 13 B 12 D 11 EOF
命令:sort [File...]
默认按第一列字符 ASCII
排序
$ sort sort.md
A 4
B 3
C 2
D 1
也可以多个文件内容一块排序
$ sort sort.md sort1.md
A 14
A 4
B 12
B 3
C 13
C 2
D 1
D 11
3. sort -r 降序排序
命令:sort -r [File...]
$ cat <<EOF | sort -r sort.md
A 4
B 3
C 2
D 1
EOF
D 1
C 2
B 3
A 4
4. sort -k 按列排序
命令:sort -k Start[,End] [File...]
列的起始值是 1, 不是 0
$ cat <<EOF | sort -k 2 sort.md
A 4
B 3
C 2
D 1
EOF
D 1
C 2
B 3
A 4
5. sort -t 指定分隔符
默认分隔符为空格,但有时候文本的分隔符为其他,这时候就可以用 -t
参数
命令:sort -t [File...]
$ cat <<EOF | sort -t : -k 2
A:14
C:13
B:12
D:11
EOF
D:11
B:12
C:13
A:14
6. 排序细节
6.1 ASCII 码排序
默认根据字符排序,即 ASCII
码排序,如果同一位置具有相同的字符,则继续比对后一位置的 ASCII
码,直到行末。
$ cat <<EOF | sort
130
121
120
14
13
1
EOF
# 从第一个字符的 ASCII 码开始对比,相同则对比下一位,以此类推
1
120
121
13
130
14
如果想根据数字大小排序,可以使用后续介绍的 -n
参数
6.2 分隔符与排序的关系
$ cat <<EOF | sort -k 1
15
1
EOF
# 这个结果大家应该没有疑问
1
15
$ cat <<EOF | sort -k 1
15 6
1 6
EOF
# 这个结果就有点出乎意料了
# 不应该 1 小于 15,排前面吗
15 6
1 6
要解答这个疑问,先看看 之前在介绍 -k
,写的这个简单的命令描述sort -k Start[,End] [File...]
实际上完整的命令描述为:sort -k F[.C][OPTS][,F[.C][OPTS]] [File...]
F
: 字段序号(field number
),即第几列,默认StartF
为第 1 列,EndF
为最后一列c
: 在字段中的第几个字符开始对比,默认StartC
在开始字段的第一个字符,截止EndC
为行末。[OPTS]
: 排序方法[bdfgiMhnRrV]
,在Start
或End
中指定都是等效的。未指定则继承全局
可以理解为 sort -k
只关注两个点之间的内容,毕竟 F
和 c
的描述的是点的位置(第几列第几个字符)。而分隔符直接过滤掉。
# 现在再回过头来看这道题
$ cat <<EOF | sort -k 1
15 6
1 6
EOF
# 这里没有指定前后两个点,所以默认是行头行尾
# 内容为本行全部,再过滤掉分隔符,剩余内容为
156
16
# 根据字符 ASCII 排序,逐字对比排序后,排序如下
156
16
# 补上分隔符
15 6
1 6
两个点之间的文本,那如果将两个点约束同个列上,例如第 1 列,能否实现我们期待的效果
$ cat <<EOF | sort -k 1,1
15 6
1 6
EOF
1 6
15 6
确实可以,这就符合我们的惯性思维了,所以尽量使用 sort -k x,x
,指定好 End
在同一列。
继续验证
# 之前的数据是
# 15 6
# 1 6
# 如果把第二行数据的 1 6 改成 1 4
# 去掉分隔符,14 比 15 小,要排前面
# 尝试一下
$ cat <<EOF | sort -k 1
15 6
1 4
EOF
# 和预想一致
1 4
15 6
那么不同分隔符对排序有影响吗?
空格的 ASCII
为 32,比数字小。我尝试过比数字大值为 124 的 |
,结论是没影响,就不补充 demo 了,有兴趣可以自己试试。
但网上有一些结论是:分隔符作为了文本参与了排序。这个结论我不认同,因为无法解释,为什么换了分隔符排序结果不受影响。
所以我还是保持观点: 分隔符在排序时直接被过滤掉
15 6
1 6
总结一下: 一开始会认为1 6
要排在15 6
前面,是主观的认为这里是两个列,对比完第一个列后,再对比第二个列。
但实际上,-k
只会记录前后两个点,由这两个点去获取中间的文本。分隔符可以分隔列,但最终目的,只是服务于找到点的位置。随后取出中间文本后便把分割符过滤了。
使用sort -k x,x
显性设定End
在同一列,符合我们的惯性思维。
还有其他小的细节,可以参考 linux sort 命令整理
7. sort -n 按数字大小排序
命令:sort -n [File...]
$ sort -nk 2 sort.md sort1.md
D 1
C 2
B 3
A 4
D 11
B 12
C 13
A 14
8. 字符串排序
前面都是以行为单位排序,也可以配合其他命令,实现以字符为单位的排序
本质是利用 grep -o
将字符串转为行,sort
排序后,tr -d
删除换行符还原为字符串。
# grep -o:--only-matching,仅仅打印匹配到的字符,相当于将 hello 分成每行一个字符
# tr -d '\n':删除所有换行符
$ echo hello | grep -o . | sort | tr -d '\n'
ehllo